package service

import (
	"context"
	"sync"
	"time"

	"hundsun.com/hsl/hschain/common/log/logging"

	"hundsun.com/hsl/hschain/rpc/common/constant"
)

//FlowControlMonitor FlowControlMonitor
type FlowControlMonitor struct {
	flowMap        map[string]int
	flowControlCtx context.Context
	tpsLimit       int
	flowChan       chan string
	lock           sync.Mutex
	log            logging.Log
}

//NewFlowControlInstance 新建
func NewFlowControlInstance(ctx context.Context, limit int, log logging.Log) *FlowControlMonitor {
	flowControl := &FlowControlMonitor{
		flowMap:        make(map[string]int),
		flowControlCtx: ctx,
		tpsLimit:       limit,
		flowChan:       make(chan string),
		log:            log,
	}
	go flowControl.monitor()
	return flowControl
}

func (f *FlowControlMonitor) monitor() {
	f.log.Infof("flow control monitor started, limit:%d", f.tpsLimit)
	duration := time.Second * constant.FlowControlTime
	ticker := time.NewTicker(duration)
	for {
		select {
		case <-f.flowControlCtx.Done():
			f.log.Infof("flow control monitor closed")
			return
		case <-ticker.C:
			//清空map
			f.lock.Lock()
			f.flowMap = make(map[string]int)
			f.lock.Unlock()
		}
	}
}

//Check 流量检查
func (f *FlowControlMonitor) Check(endpoint string) bool {
	f.lock.Lock()
	defer f.lock.Unlock()
	value, ok := f.flowMap[endpoint]
	if !ok {
		f.flowMap[endpoint] = 1
		return true
	}
	value++
	if value > f.tpsLimit && f.tpsLimit > 0 {
		return false
	}
	f.flowMap[endpoint] = value
	return true
}
